// FacebookIFrameSession.cs
// Facebook/FrameworkWeb/Web
// Copyright (c) 2007, Nikhil Kothari. All Rights Reserved.
//

using System;
using System.Diagnostics;
using System.Web;
using System.Web.UI;
using Facebook.Service.Core;

namespace Facebook.Web
{

	internal sealed class FacebookIFrameSession : FacebookServerSession
	{

		private bool _stateLoaded;

		private string _sessionKeyState;
		private string _userIDState;
		private bool _sessionExpiresState;
		private string _pageUserIDState;

		private string _referrer;

		public FacebookIFrameSession(FacebookApplication application, string appKey, string secret)
			: base(application, appKey, secret)
		{
		}

		protected internal override string Initialize(HttpContext context)
		{
			base.Initialize(context);

			string redirectUrl = null;
			HttpRequest request = context.Request;

			FacebookSessionType sessionType = FacebookSessionType.User;

			string sessionKey = request["fb_sig_session_key"];
			bool sessionExpires = (String.CompareOrdinal(request["fb_sig_expires"], "0") != 0);
			string userID = request["fb_sig_user"];
			string pageUserID = null;

			if (String.IsNullOrEmpty(request["fb_page_id"]) == false)
			{
				pageUserID = userID;
				userID = request["fb_page_id"];
			}

			if (_stateLoaded &&
				(String.IsNullOrEmpty(sessionKey) || String.IsNullOrEmpty(userID)))
			{
				sessionKey = _sessionKeyState;
				sessionExpires = _sessionExpiresState;
				userID = _userIDState;
				pageUserID = _pageUserIDState;
			}

			if (String.IsNullOrEmpty(sessionKey) || String.IsNullOrEmpty(userID))
			{
				string authToken = request["auth_token"];

				if (String.IsNullOrEmpty(authToken) == false)
				{
					FacebookRequest sessionRequest = new FacebookRequest(this);
					string dummy;

					sessionKey = sessionRequest.CreateSession(authToken, out userID, out sessionExpires, out dummy);
					Debug.Assert(String.IsNullOrEmpty(dummy));
				}
			}

			if (!String.IsNullOrEmpty(sessionKey) && !String.IsNullOrEmpty(userID))
			{
				if (String.IsNullOrEmpty(pageUserID) == false)
				{
					sessionType = FacebookSessionType.PresencePage;
				}
				InitializeSessionKey(sessionKey, sessionExpires, sessionType);
				InitializeUserID(userID, pageUserID);
			}
			else if (Application.RequiresLogin && !Application.RequiresAppAdded)
			{
				// Note that we skip over this and redirect in the next block, if the 
				// application must be added but the requires login is false.
				redirectUrl = String.Format(FacebookLoginUrl, ApplicationKey);
			}

			if ((redirectUrl == null) && (Application.IsApplicationAdded == false &&
				 Application.RequiresAppAdded))
			{
				if (Application.InNewProfile)
				{
					redirectUrl = String.Format(FacebookLoginUrl, ApplicationKey);
				}
				else
				{
					redirectUrl = String.Format(FacebookAddAppUrl, ApplicationKey);
				}
			}

			// If we're redirecting, append parameters where specified
			if (redirectUrl != null)
			{
				if (Application.RedirectCanvas)
					redirectUrl += "&canvas";

				if (!String.IsNullOrEmpty(Application.RedirectNext))
				{
					redirectUrl += "&next=" +
						 System.Web.HttpUtility.UrlEncode(Application.RedirectNext);
				}
			}

			if (_referrer == null)
			{
				if (request.UrlReferrer == null)
				{
					_referrer = request.Url.AbsoluteUri;
				}
				else
				{
					_referrer = request.UrlReferrer.AbsoluteUri;
				}
			}

			return redirectUrl;
		}

		protected internal override void LoadState(object state)
		{
			Debug.Assert(state != null);
			Debug.Assert(state is Triplet);

			Triplet t = (Triplet)state;
			Pair sessionState = (Pair)t.First;
			Pair userState = (Pair)t.Second;

			_sessionKeyState = (string)sessionState.First;
			_sessionExpiresState = (bool)sessionState.Second;

			_userIDState = (string)userState.First;
			_pageUserIDState = (string)userState.Second;

			_referrer = (string)t.Third;

			_stateLoaded = true;
		}

		protected internal override object SaveState()
		{
			Pair sessionState = new Pair(SessionKey, SessionExpires);
			Pair userState = new Pair(UserID, PageUserID);

			return new Triplet(sessionState, userState, _referrer);
		}

		public string ResolveUrl(HttpContext context, string url)
		{
			Uri uri = new Uri(url, UriKind.RelativeOrAbsolute);

			if (uri.IsAbsoluteUri == false)
			{
				Uri referrerUri = new Uri(_referrer, UriKind.Absolute);
				Uri resolvedUri = new Uri(referrerUri, uri);
				url = resolvedUri.AbsoluteUri;

				if (Application.Session.SessionType == FacebookSessionType.PresencePage)
				{
					int queryIndex = url.IndexOf('?');

					url += queryIndex >= 0 ? "&" : "?";
					url += "fb_page_id=" + Application.UserID;
				}
			}
			return url;
		}
	}
}
